package com.bsj.travel.monitor.utils;

import com.alibaba.fastjson2.JSON;
import com.bsj.travel.def.monitor.job.SysJob;
import com.bsj.travel.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;

/**
 * @author yinhao
 * @version 1.0
 * @description 定时任务工具
 * @date 2024/1/23
 */
@Slf4j
public class ScheduleUtils {

    public static final String TASK_CLASS = "TASK_CLASS";
    /** 执行目标key */
    public static final String TASK_PROPERTIES = "TASK_PROPERTIES";

    /**
     * 获取到对应的quartz类
     * @param sysJob 执行任务对象
     * @return 具体的quartz类
     */
    private static Class<? extends Job> getQuartzJobClass(SysJob sysJob) {
        boolean isConcurrent = sysJob.getConcurrent() == 0;
        return isConcurrent ? QuartzJobExecution.class : QuartDisallowConcurrentExecution.class;
    }

    /**
     * 构建任务启动对象
     * @param jobId 任务ID
     * @param jobGroup 任务组别
     * @return
     */
    public static TriggerKey getTriggerKey(Long jobId, String jobGroup) {
        return TriggerKey.triggerKey(TASK_CLASS + jobId, jobGroup);
    }

    /**
     * 构建任务键对象
     * @param jobId 任务ID
     * @param jobGroup 任务组别
     * @return
     */
    public static JobKey getJobKey(Long jobId, String jobGroup) {
        return JobKey.jobKey(TASK_CLASS + jobId, jobGroup);
    }

    /**
     * 设置定时策略
     * @param job 任务对象
     * @param cb 表示器
     * @return
     */
    public static CronScheduleBuilder handleCronSchedulePolicy(SysJob job, CronScheduleBuilder cb) {
        switch (job.getMisfirePolicy()) {
            case 0:
                return cb;
            case 1:
                return cb.withMisfireHandlingInstructionIgnoreMisfires();
            case 2:
                return cb.withMisfireHandlingInstructionFireAndProceed();
            case 3:
                return cb.withMisfireHandlingInstructionDoNothing();
            default:
                return null;
        }
    }

    /**
     * 创建定时任务
     * @param scheduler 定时任务创建器
     * @param job 自定义定时任务对象
     * @throws SchedulerException
     */
    public static void createScheduleJob(Scheduler scheduler, SysJob job) throws SchedulerException {
        Class<? extends Job> jobClass = getQuartzJobClass(job);
        //创建Job信息
        Long jobId = job.getJobId();
        String jobGroup = job.getJobGroup();
        JobDetail jobDetail = JobBuilder.newJob(jobClass)
                .withIdentity(getJobKey(jobId, jobGroup)).build();
        //表达式构造器
        CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
        cronScheduleBuilder = handleCronSchedulePolicy(job, cronScheduleBuilder);
        //按照新的表达式构建trigger
        CronTrigger trigger = TriggerBuilder.newTrigger()
                .withIdentity(getTriggerKey(jobId, jobGroup))
                .withSchedule(cronScheduleBuilder).build();
        //放入参数，运行时方法获取
//        jobDetail.getJobDataMap().put(TASK_PROPERTIES, job);
        jobDetail.getJobDataMap().put(TASK_PROPERTIES, JSON.toJSONString(job));
        if (scheduler.checkExists(getJobKey(jobId, jobGroup))) {
            //防止创建时存在数据问题，移除后再执行创建操作
            scheduler.deleteJob(getJobKey(jobId, jobGroup));
        }
        //判断任务是否过期
        if (StringUtils.isNotNull(CronUtils.getNextExecution(job.getCronExpression()))) {
            scheduler.scheduleJob(jobDetail, trigger);
        }
        //暂停任务
        if (job.getStatus() == 1) {
            scheduler.pauseJob(ScheduleUtils.getJobKey(jobId, jobGroup));
        }
    }
}
